// 模拟lodash中的flowRight 函数组合
const reverse = (arr) => arr.reverse();
const first = (arr) => arr[0];
const toUpper = (s) => s.toUpperCase();

function compose(...args) {
    return function (value) {
        // reduce的第一个参数是一个函数，函数内第一个参数是一个累计的结果,第二个参数是调用reduce的当前值
        // 第二个参数是初始值
        return args.reverse().reduce(function (acc, fn) {
            return fn(acc);
        }, value);
    };
}

// ES6写法
const compose = (...args) => (value) =>
    args.reverse().reduce((acc, fn) => fn(acc), value);

const f = compose(toUpper, first, reverse);

console.log(f(["one", "two", "three"]));

// 结合律（associativity） 
let f = compose(f, g, h) 
let associative = compose(compose(f, g), h) == compose(f, compose(g, h)) 

// 函数组合要满足结合律
const associative = compose(toUpper, compose(first, reverse));
console.log(associative(["one", "two", "three"]));
